﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using RestSharp;
using RestSharp.Authenticators.OAuth;
using RestSharp.Authenticators;
namespace GoTo
{
    public class Meeting
    {

        const string BaseUrl = "https://api.citrixonline.com";

        private string oAuthToken { get; set; }

        /// <summary>
        /// Use when JSON serialization to properties is needed
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <returns></returns>
        protected T Execute<T>(RestRequest request) where T : new()
        {

            var client = new RestClient();
            client.BaseUrl = BaseUrl;
            request.AddHeader("Authorization", "OAuth oauth_token=" + oAuthToken);

            var response = client.Execute<T>(request);

            if (response.ErrorException != null || response.ErrorMessage != null)
            {
                var ConnectionException = new Exception(response.ErrorMessage);
                throw ConnectionException;
            }

            var RestException = new Exception(response.StatusCode.ToString());
            switch (response.StatusCode)
            {
                case System.Net.HttpStatusCode.OK:
                    break;
                case System.Net.HttpStatusCode.Created:
                    break;
                case System.Net.HttpStatusCode.BadGateway:
                    throw RestException;
                case System.Net.HttpStatusCode.BadRequest:
                    throw RestException;
                case System.Net.HttpStatusCode.Forbidden:
                    throw RestException;
                case System.Net.HttpStatusCode.InternalServerError:
                    throw RestException;
                case System.Net.HttpStatusCode.NotFound:
                    throw RestException;
                case System.Net.HttpStatusCode.Unauthorized:
                    throw RestException;
                case System.Net.HttpStatusCode.RequestTimeout:
                    throw RestException;
                default:
                    break;
            }

            return response.Data;
        }

        /// <summary>
        /// Use when no JSON serialization is needed
        /// </summary>
        /// <param name="request"></param>
        /// <returns>System.Net.HttpStatusCode</returns>
        protected System.Net.HttpStatusCode Execute(RestRequest request)
        {

            var client = new RestClient();
            client.BaseUrl = BaseUrl;
            request.AddHeader("Authorization", "OAuth oauth_token=" + oAuthToken);

            var response = client.Execute(request);

            if (response.ErrorException != null || response.ErrorMessage != null)
            {
                var ConnectionException = new Exception(response.ErrorMessage);
                throw ConnectionException;
            }

            var RestException = new Exception(response.StatusCode.ToString());
            switch (response.StatusCode)
            {
                case System.Net.HttpStatusCode.OK:
                    break;
                case System.Net.HttpStatusCode.Created:
                    break;
                case System.Net.HttpStatusCode.BadGateway:
                    throw RestException;
                case System.Net.HttpStatusCode.BadRequest:
                    throw RestException;
                case System.Net.HttpStatusCode.Forbidden:
                    throw RestException;
                case System.Net.HttpStatusCode.InternalServerError:
                    throw RestException;
                case System.Net.HttpStatusCode.NotFound:
                    throw RestException;
                case System.Net.HttpStatusCode.RequestTimeout:
                    throw RestException;
                default:
                    break;
            }

            return response.StatusCode;
        }

        public enum ConferenceCallTypes { PSTN, Hybrid, Private, VOIP }
        public enum MeetingTypes { Immediate, Scheduled, Recurring }
        public enum ProductTypes { G2M, G2W, G2T, OPENVOICE }
        public enum Statuses { active, suspended }

        private RestRequest GTMrequest(Method method)
        {

            //Method reserved for future use

            var request = new RestRequest(method);
            return request;
        }

        public class GetMeeting : Meeting
        {
            public class Response
            {
                public string status { get; set; }
                public string subject { get; set; }
                public string startTime { get; set; }
                public string conferenceCallInfo { get; set; }
                public string passwordRequired { get; set; }
                public string meetingType { get; set; }
                public string maxParticipants { get; set; }
                public string endTime { get; set; }
                public string uniqueMeetingId { get; set; }
                public string meetingId { get; set; }
                public string createTime { get; set; }
                //Error Properties
                public string int_err_code { get; set; }
                public string msg { get; set; }
            }

            /// <summary>
            /// Required
            /// </summary>
            public string MeetingID { get; set; }

            /// <summary>
            /// Returns the meeting details for the specified meeting. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetMeeting(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns></returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/meetings/{meetingId}";
                request.AddParameter("meetingId", MeetingID.RemoveDashes(), ParameterType.UrlSegment);
                return Execute<List<Response>>(request);
            }
        }

        public class GetMeetings : Meeting
        {
            public class Response
            {
                public string status { get; set; }
                public string subject { get; set; }
                public string startTime { get; set; }
                public string conferenceCallInfo { get; set; }
                public string passwordRequired { get; set; }
                public string meetingType { get; set; }
                public string maxParticipants { get; set; }
                public string endTime { get; set; }
                public string uniqueMeetingId { get; set; }
                public string meetingId { get; set; }
                public string createTime { get; set; }
                public string date { get; set; }
                public string duration { get; set; }
                public string organizerkey { get; set; }
                public string meetingInstanceKey { get; set; }
                public string numAttendees { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }
            }

            /// <summary>
            /// Optional If yes, StartDate and EndDate are required. Up to 60 days of history.
            /// </summary>
            public bool History { get; set; }
            /// <summary>
            /// Required if History is True.
            /// </summary>
            public DateTime StartDate { get; set; }
            /// <summary>
            /// Required if History is True.
            /// </summary>
            public DateTime EndDate { get; set; }

            /// <summary>
            /// Gets future meetings for specified organizer.
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetMeetings(string oauth)
            {
                oAuthToken = oauth;
            }

            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                if (History)
                {
                    StartDate = DateTime.Now.AddDays(-10);
                    EndDate = DateTime.Now.AddDays(-1);
                    request.AddParameter("history", "true", ParameterType.QueryString);

                }
                else
                {
                    StartDate = DateTime.Now;
                    EndDate = DateTime.Now.AddDays(60);
                    request.AddParameter("scheduled", "true", ParameterType.QueryString);
                }

                request.Resource = "G2M/rest/meetings";
                request.AddParameter("startDate", StartDate.ToISO8601UTC(), ParameterType.QueryString);
                request.AddParameter("endDate", EndDate.ToISO8601UTC(), ParameterType.QueryString);
                return Execute<List<Response>>(request);
            }
        }

        public class CreateMeeting : Meeting
        {
            public class Response
            {
                public Uri joinURL { get; set; }
                public string maxParticipants { get; set; }
                public string uniqueMeetingId { get; set; }
                public string conferenceCallInfo { get; set; }
                public string meetingId { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }
            }

            /// <summary>
            /// Optional Default meeting Subject is "My GoToMeeting"
            /// </summary>
            public string Subject { get; set; }
            /// <summary>
            /// Optional Default StartTime is 1 minute in the future
            /// </summary>
            public DateTime StartTime { get; set; }
            /// <summary>
            /// Optional Default EndTime is 1 hour in the future
            /// </summary>
            public DateTime EndTime { get; set; }
            /// <summary>
            /// Optional Default ConferenceCallType is Hybrid
            /// </summary>
            public ConferenceCallTypes ConferenceCallType { get; set; }
            /// <summary>
            /// Optional Default MeetingType is Scheduled
            /// </summary>
            public MeetingTypes MeetingType { get; set; }


            /// <summary>
            /// Create a new meeting based on the parameters specified. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public CreateMeeting(string oauth)
            {
                Subject = "My GoToMeeting";
                StartTime = DateTime.Now.AddMinutes(1);
                EndTime = DateTime.Now.AddHours(1);
                ConferenceCallType = ConferenceCallTypes.Hybrid;
                MeetingType = MeetingTypes.Scheduled;
                oAuthToken = oauth;
            }
            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.POST);
                request.Resource = "G2M/rest/meetings";
                request.RequestFormat = DataFormat.Json;
                request.AddBody(new { subject = Subject, starttime = StartTime, endtime = EndTime, passwordrequired = "false", conferencecallinfo = ConferenceCallType.ToString(), timezonekey = "", meetingtype = MeetingType.ToString() });
                return Execute<List<Response>>(request);
            }
        }

        public class DeleteMeeting : Meeting
        {

            /// <summary>
            /// Required 
            /// </summary>
            public string MeetingId { get; set; }

            /// <summary>
            /// Delete the meeting identified by the meeting key. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public DeleteMeeting(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response "No Content" means meeting was deleted</returns>
            public System.Net.HttpStatusCode Go()
            {
                var request = GTMrequest(Method.DELETE);
                request.Resource = "G2M/rest/meetings/{meetingId}";
                request.AddParameter("meetingId", MeetingId.RemoveDashes(), ParameterType.UrlSegment);
                return Execute(request);
            }
        }

        public class UpdateMeeting : Meeting
        {

            /// <summary>
            /// Required
            /// </summary>
            public string MeetingID { get; set; }
            /// <summary>
            /// Required
            /// </summary>
            public string Subject { get; set; }
            /// <summary>
            /// Required
            /// </summary>
            public DateTime StartTime { get; set; }
            /// <summary>
            /// Required
            /// </summary>
            public DateTime EndTime { get; set; }
            /// <summary>
            /// Required
            /// </summary>
            public ConferenceCallTypes ConferenceCallType { get; set; }
            /// <summary>
            /// Required
            /// </summary>
            public MeetingTypes MeetingType { get; set; }
            /// <summary>
            /// Use only when meeting is recurring
            /// </summary>
            public string UniqueMeetingInstance { get; set; }

            /// <summary>
            /// Update an existing meeting specified by meeting id. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public UpdateMeeting(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response "No Content" means meeting was updated</returns>
            public System.Net.HttpStatusCode Go()
            {
                var request = GTMrequest(Method.PUT);
                request.Resource = "G2M/rest/meetings/{meetingId}";
                request.AddParameter("meetingId", MeetingID.RemoveDashes(), ParameterType.UrlSegment);
                request.RequestFormat = DataFormat.Json;
                if (UniqueMeetingInstance == null)
                {
                    request.AddBody(new { subject = Subject, starttime = StartTime, endtime = EndTime, passwordrequired = "false", conferencecallinfo = ConferenceCallType.ToString(), timezonekey = "", meetingtype = MeetingType.ToString() });
                }
                else
                {
                    request.AddBody(new { subject = Subject, starttime = StartTime, endtime = EndTime, passwordrequired = "false", conferencecallinfo = ConferenceCallType.ToString(), timezonekey = "", meetingtype = MeetingType.ToString(), uniqueMeetingInstance = UniqueMeetingInstance });
                }
                return Execute(request);
            }
        }

        public class StartMeeting : Meeting
        {
            public class Response
            {
                public Uri hostURL { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }
            }

            /// <summary>
            /// Required
            /// </summary>
            public string MeetingID { get; set; }


            /// <summary>
            /// Returns a host URL that can be used to start a meeting. Send the user browser to host URL, the GoToMeeting client will be downloaded and launched and the meeting will start. Doesn't require the end user to login to client. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public StartMeeting(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/meetings/{meetingId}/start";
                request.RequestFormat = DataFormat.Json;
                request.AddParameter("meetingId", MeetingID.RemoveDashes(), ParameterType.UrlSegment);
                return Execute<List<Response>>(request);
            }
        }

        public class GetMeetingByGroup : Meeting
        {
            public class Response
            {
                public string organizerkey { get; set; }
                public string firstname { get; set; }
                public string lastname { get; set; }
                public string email { get; set; }
                public string groupName { get; set; }
                public string meetingInstanceKey { get; set; }
                public string meetingId { get; set; }
                public string subject { get; set; }
                public string meetingType { get; set; }
                public string duration { get; set; }
                public string startTime { get; set; }
                public string endTime { get; set; }
                public string conferenceCallInfo { get; set; }
                public string numAttendees { get; set; }


                public string int_err_code { get; set; }
                public string msg { get; set; }


            }

            /// <summary>
            /// Required GroupKey is returned from GetGroups Method
            /// </summary>
            public string GroupKey { get; set; }
            /// <summary>
            /// Optional: If set to True, Default is last 10 days, Up to 60 days of history.
            /// </summary>
            public bool History { get; set; }
            /// <summary>
            /// Required if History is True, maximum 60 days of history.
            /// </summary>
            public DateTime StartDate { get; set; }
            /// <summary>
            /// Required if History is True, must be at least 1 day in the past.
            /// </summary>
            public DateTime EndDate { get; set; }

            /// <summary>
            /// Get Future meetings for group.
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetMeetingByGroup(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                this.History = History;
                if (History)
                {
                    StartDate = DateTime.Now.AddDays(-10);
                    EndDate = DateTime.Now.AddDays(-1);
                    request.AddParameter("history", "true", ParameterType.QueryString);
                }
                else
                {
                    StartDate = DateTime.Now;
                    EndDate = DateTime.Now.AddDays(60);
                    request.AddParameter("scheduled", "true", ParameterType.QueryString);
                }
                request.Resource = "G2M/rest/groups/{groupKey}/meetings";
                request.AddParameter("groupKey", GroupKey, ParameterType.UrlSegment);
                request.AddParameter("startDate", StartDate.ToISO8601UTC(), ParameterType.QueryString);
                request.AddParameter("endDate", EndDate.ToISO8601UTC(), ParameterType.QueryString);
                return Execute<List<Response>>(request);
            }

        }

        public class GetMeetingsByOrganizer : Meeting
        {
            public class Response
            {

                public string organizerkey { get; set; }
                public string firstname { get; set; }
                public string lastname { get; set; }
                public string email { get; set; }
                public string groupName { get; set; }
                public string meetingInstanceKey { get; set; }
                public string meetingId { get; set; }
                public string subject { get; set; }
                public string meetingType { get; set; }
                public string duration { get; set; }
                public string startTime { get; set; }
                public string endTime { get; set; }
                public string conferenceCallInfo { get; set; }
                public string numAttendees { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }

            }


            /// <summary>
            /// Required 
            /// </summary>
            public string OrganizerKey { get; set; }
            /// <summary>
            /// Optional If yes, StartDate and EndDate are required. Up to 60 days of history.
            /// </summary>
            public bool History { get; set; }
            /// <summary>
            /// Required if History is True.
            /// </summary>
            public DateTime StartDate { get; set; }
            /// <summary>
            /// Required if History is True.
            /// </summary>
            public DateTime EndDate { get; set; }


            /// <summary>
            /// Get future meetings for Organizer. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetMeetingsByOrganizer(string oauth)
            {
                oAuthToken = oauth;

            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                if (History)
                {
                    StartDate = DateTime.Now.AddDays(-10);
                    EndDate = DateTime.Now.AddDays(-1);
                    request.AddParameter("history", "true", ParameterType.QueryString);

                }
                else
                {
                    StartDate = DateTime.Now;
                    EndDate = DateTime.Now.AddDays(60);
                    request.AddParameter("scheduled", "true", ParameterType.QueryString);
                }
                request.Resource = "G2M/rest/organizers/{organizerKey}/meetings";
                request.AddParameter("organizerKey", OrganizerKey, ParameterType.UrlSegment);
                request.AddParameter("startDate", StartDate.ToISO8601UTC(), ParameterType.QueryString);
                request.AddParameter("endDate", EndDate.ToISO8601UTC(), ParameterType.QueryString);
                return Execute<List<Response>>(request);
            }
        }

        public class CreateOrganizer : Meeting
        {
            //need to test

            /// <summary>
            /// Required GroupKey is returned from GetGroups Method
            /// </summary>
            public string GroupKey { get; set; }
            /// <summary>
            /// Required
            /// </summary>
            public string OrganizerEmail { get; set; }
            /// <summary>
            /// Required
            /// </summary>
            public string FirstName { get; set; }
            /// <summary>
            /// Required
            /// </summary>
            public string LastName { get; set; }
            /// <summary>
            /// Required GoToMeeting is the Default
            /// </summary>
            public ProductTypes ProductType { get; set; }

            /// <summary>
            /// Creates a new organizer. Returns an empty response and sends an email to the email defined in request.
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public CreateOrganizer(string oauth)
            {
                oAuthToken = oauth;
                ProductType = ProductTypes.G2M;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public System.Net.HttpStatusCode Go()
            {
                var request = GTMrequest(Method.POST);
                request.Resource = "G2M/rest/groups/{groupKey}/organizers";
                request.AddParameter("groupKey", GroupKey, ParameterType.UrlSegment);
                request.AddBody(new { organizerEmail = OrganizerEmail, firstName = FirstName, lastname = LastName, productType = ProductType });
                return Execute(request);
            }

        }

        public class DeleteOrganizer : Meeting
        {
            //need to test

            /// <summary>
            /// Required
            /// </summary>
            public string OrganizerKey { get; set; }


            /// <summary>
            ///Deletes the individual organizer specified by the organizer key. This API is only available to corporate users with the admin role. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public DeleteOrganizer(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public System.Net.HttpStatusCode Go()
            {
                var request = GTMrequest(Method.DELETE);
                request.Resource = "G2M/rest/organizers/{organizerKey}";
                request.AddParameter("organizerKey", OrganizerKey, ParameterType.UrlSegment);
                return Execute(request);
            }

        }

        public class DeleteOrganizerByEmail : Meeting
        {
            //need to test

            /// <summary>
            /// Required
            /// </summary>
            public string OrganizerEmail { get; set; }


            /// <summary>
            ///Delete the individual organizer specified by the email address. This API is only available to corporate users with the admin role
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public DeleteOrganizerByEmail(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public System.Net.HttpStatusCode Go()
            {
                var request = GTMrequest(Method.DELETE);
                request.Resource = "G2M/rest/organizers";
                request.AddParameter("email", OrganizerEmail, ParameterType.QueryString);
                return Execute(request);
            }


        }

        public class GetOrganizer : Meeting
        {

            //need to test
            public class Response
            {
                public string organizerkey { get; set; }
                public string groupkey { get; set; }
                public string email { get; set; }
                public string firstname { get; set; }
                public string lastname { get; set; }
                public string groupName { get; set; }
                public string status { get; set; }
                public string maxnumattendeesallowed { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }

            }
            /// <summary>
            /// Required
            /// </summary>
            public string OrganizerKey { get; set; }


            /// <summary>
            ///Returns the individual organizer specified by the organizer key. This API is only available to corporate users with the admin role. (Exception: any organizer can make this call for their own organizerKey.) 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetOrganizer(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/organizers/{organizerKey}";
                request.AddParameter("organizerKey", OrganizerKey, ParameterType.UrlSegment);
                return Execute<List<Response>>(request);
            }


        }

        public class GetOrganizerByEmail : Meeting
        {
            //need to test
            public class Response
            {
                public string organizerkey { get; set; }
                public string groupkey { get; set; }
                public string email { get; set; }
                public string firstname { get; set; }
                public string lastname { get; set; }
                public string groupName { get; set; }
                public string status { get; set; }
                public string maxnumattendeesallowed { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }


            }
            /// <summary>
            /// Required
            /// </summary>
            public string OrganizerEmail { get; set; }


            /// <summary>
            ///Gets the individual organizer specified by the organizers email. If an organizer does not have an organizerKey then they have not completed the confirmation process for their account (i.e., have not accepted the invite and created an account password). This API is only available to corporate users with the admin role
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetOrganizerByEmail(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/organizers";
                request.AddParameter("email", OrganizerEmail, ParameterType.QueryString);
                return Execute<List<Response>>(request);
            }
        }

        public class GetOrganizerByGroup : Meeting
        {

            //need to test
            public class Response
            {
                public string organizerkey { get; set; }
                public string groupkey { get; set; }
                public string email { get; set; }
                public string firstname { get; set; }
                public string lastname { get; set; }
                public string groupName { get; set; }
                public string status { get; set; }
                public string maxnumattendeesallowed { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }
            }
            /// <summary>
            /// Required
            /// </summary>
            public string GroupKey { get; set; }


            /// <summary>
            ///Returns all the organizers within a specific group. If an organizer does not have an organizerKey then they have not completed the confirmation process for their account (i.e. accepted the invite and created an account password). This API is only available to corporate users with the admin role
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetOrganizerByGroup(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/groups/{groupKey}/organizers";
                request.AddParameter("groupKey", GroupKey, ParameterType.UrlSegment);
                return Execute<List<Response>>(request);
            }

        }

        public class UpdateOrganizer : Meeting
        {

            //need to test

            /// <summary>
            /// Required
            /// </summary>
            public string OrganizerKey { get; set; }
            public Statuses Status { get; set; }

            /// <summary>
            ///Updates the specified organizer status. Status can either by "active" or "suspended". Suspending an organizer disables their access to GoToMeeting. This API is only available to corporate users with the admin role. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public UpdateOrganizer(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public System.Net.HttpStatusCode Go()
            {
                var request = GTMrequest(Method.PUT);
                request.Resource = "G2M/rest/organizers/{organizerKey}";
                request.AddParameter("organizerKey", OrganizerKey, ParameterType.UrlSegment);
                request.AddBody(new { status = Status });
                return Execute(request);
            }
        }

        public class GetAttendeesByGroup : Meeting
        {
            //need to test
            public class Response
            {
                public string organizerkey { get; set; }
                public string groupkey { get; set; }
                public string email { get; set; }
                public string firstname { get; set; }
                public string lastname { get; set; }
                public string groupName { get; set; }
                public string status { get; set; }
                public string meetingInstanceKey { get; set; }
                public string maxnumattendeesallowed { get; set; }
                public string meetingId { get; set; }
                public string subject { get; set; }
                public string meetingType { get; set; }
                public string duration { get; set; }
                public string startTime { get; set; }
                public string endTime { get; set; }
                public string conferenceCallInfo { get; set; }
                public string numAttendees { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }

            }
            /// <summary>
            /// Required
            /// </summary>
            public string GroupKey { get; set; }
            /// <summary>
            /// Required Default is 10 days ago
            /// </summary>
            public DateTime StartDate { get; set; }
            /// <summary>
            /// Required Default is 1 day ago
            /// </summary>
            public DateTime EndDate { get; set; }

            /// <summary>
            ///Returns all attendees for all meetings within specified date range held by organizers within the specified group. This API is only available to corporate users with the admin role. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetAttendeesByGroup(string oauth)
            {
                oAuthToken = oauth;
                StartDate = DateTime.Now.AddDays(-10);
                EndDate = DateTime.Now.AddDays(-1);
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/groups/{groupKey}/attendees";
                request.AddParameter("groupkey", GroupKey, ParameterType.UrlSegment);
                request.AddParameter("startdate", StartDate.ToISO8601UTC(), ParameterType.QueryString);
                request.AddParameter("enddate", EndDate.ToISO8601UTC(), ParameterType.QueryString);
                return Execute<List<Response>>(request);
            }
        }

        public class GetAttendeesByMeeting : Meeting
        {
            //need to test
            public class Response
            {
                public string organizerkey { get; set; }
                public string email { get; set; }
                public string firstname { get; set; }
                public string lastname { get; set; }
                public string groupName { get; set; }
                public string meetingInstanceKey { get; set; }
                public string meetingId { get; set; }
                public string subject { get; set; }
                public string meetingType { get; set; }
                public string duration { get; set; }
                public string startTime { get; set; }
                public string endTime { get; set; }
                public string conferenceCallInfo { get; set; }
                public string numAttendees { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }

            }
            /// <summary>
            /// Required
            /// </summary>
            public string MeetingInstanceKey { get; set; }
            /// <summary>
            /// Required Default is 10 days ago
            /// </summary>
            public DateTime StartDate { get; set; }
            /// <summary>
            /// Required Default is 1 day ago
            /// </summary>
            public DateTime EndDate { get; set; }

            /// <summary>
            ///List all attendees for specified meeting instance key. Meeting instance key can be found for historical meetings using Get Meetings, Get Meetings by Organizer, and Get Meetings by Group. The meeting instance key is only available for meetings that were successfully started. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetAttendeesByMeeting(string oauth)
            {
                oAuthToken = oauth;
                StartDate = DateTime.Now.AddDays(-10);
                EndDate = DateTime.Now.AddDays(-1);
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/meetings/{meetingInstanceKey}/attendees";
                request.AddParameter("meetingInstanceKey", MeetingInstanceKey, ParameterType.UrlSegment);
                request.AddParameter("startdate", StartDate.ToISO8601UTC(), ParameterType.QueryString);
                request.AddParameter("enddate", EndDate.ToISO8601UTC(), ParameterType.QueryString);
                return Execute<List<Response>>(request);
            }
        }

        public class GetAttendeesByOrganizer : Meeting
        {

            //need to test
            public class Response
            {

                public string name { get; set; }
                public string meetingId { get; set; }
                public string email { get; set; }
                public string startTime { get; set; }
                public string endTime { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }


            }
            /// <summary>
            /// Required
            /// </summary>
            public string OrganizerKey { get; set; }
            /// <summary>
            /// Required default is 10 days ago
            /// </summary>
            public DateTime StartDate { get; set; }
            /// <summary>
            /// Required default is 1 days ago
            /// </summary>
            public DateTime EndDate { get; set; }

            /// <summary>
            ///Lists all attendees for all meetings within specified date range for a specified organizer. This API is only available to corporate users with the admin role. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetAttendeesByOrganizer(string oauth)
            {
                oAuthToken = oauth;
                StartDate = DateTime.Now.AddDays(-10);
                EndDate = DateTime.Now.AddDays(-1);
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/organizers/{organizerKey}/attendees";
                request.AddParameter("organizerKey", OrganizerKey, ParameterType.UrlSegment);
                request.AddParameter("startdate", StartDate.ToISO8601UTC(), ParameterType.QueryString);
                request.AddParameter("enddate", EndDate.ToISO8601UTC(), ParameterType.QueryString);
                return Execute<List<Response>>(request);
            }

        }

        public class GetGroups : Meeting
        {

            public class Response
            {
                public string groupName { get; set; }
                public string groupkey { get; set; }
                public string parentKey { get; set; }
                public string status { get; set; }
                public string numOrganizers { get; set; }

                public string int_err_code { get; set; }
                public string msg { get; set; }
            }
            /// <summary>
            /// List all groups for an account. This API is only available to corporate users with the admin role. 
            /// </summary>
            /// <param name="oauth">OAuth Token String</param>
            public GetGroups(string oauth)
            {
                oAuthToken = oauth;
            }

            /// <summary>
            /// Send Request
            /// </summary>
            /// <returns>Response</returns>
            public List<Response> Go()
            {
                var request = GTMrequest(Method.GET);
                request.Resource = "G2M/rest/groups";

                return Execute<List<Response>>(request);
            }

        }
    }

    public class Webinar
    {
        public class CreateRegistrant : Webinar
        { }

        public class GetRegistrant : Webinar
        { }

        public class GetRegistrants : Webinar
        { }

        public class RegistrationFields : Webinar
        { }

        public class GetAttendee : Webinar
        { }

        public class GetAttendeePollAnswers : Webinar
        { }

        public class GetAttendeeQuestions : Webinar
        { }

        public class GetAttendeeSurveyAnswers : Webinar
        { }

        public class GetAttendeesForAllWebinarSessions : Webinar
        { }

        public class GetHistoricalWebinars : Webinar
        { }

        public class GetUpcomingWebinars : Webinar
        { }

        public class GetWebinar : Webinar
        { }

        public class GetWebinarMeetingTimes : Webinar
        { }

        public class GetOrganizerSessions : Webinar
        { }

        public class GetSession : Webinar
        { }

        public class GetSessionAttendees : Webinar
        { }

        public class GetSessionPerformance : Webinar
        { }

        public class GetSessionPolls : Webinar
        { }

        public class GetSessionQuestions : Webinar
        { }

        public class GetSessionSurveys : Webinar
        { }

        public class GetWebinarSessions : Webinar
        { }

    }

    public class Training
    {

        public class CancelRegistration : Training
        { }

        public class GetAttendanceDetails : Training
        { }

        public class GetRegistrant : Training
        { }

        public class GetSessionsByDateRange : Training
        { }

        public class GetSessionsByTraining : Training
        { }

        public class GetTrainingRegistrants : Training
        { }

        public class RegisterForTraining : Training
        { }

        public class CreateTraining : Training
        { }

        public class DeleteTraining : Training
        { }

        public class GetManageTrainingURL : Training
        { }

        public class GetTraining : Training
        { }

        public class GetTrainings : Training
        { }

        public class UpdateTrainingNameandDescription : Training
        { }

        public class UpdateTrainingOrganizers : Training
        { }

        public class UpdateTrainingRegistrationSettings : Training
        { }

        public class UpdateTrainingTimes : Training
        { }

        public class GetOrganizers : Training
        { }

        public class GetOrganizersbyTraining : Training
        { }


    }

    public class AssistRS
    {
        public class AssociateTicket : AssistRS
        { }

        public class CreateTicket : AssistRS
        { }

        public class SearchTicket : AssistRS
        { }

        public class CreatePartnerSystemLinks : AssistRS
        { }

        public class DeletePartnerSystemLink : AssistRS
        { }

        public class GetPartnerSystemLinkInfo : AssistRS
        { }

        public class DownloadRecordings : AssistRS
        { }

        public class GetAvailableRecordings : AssistRS
        { }

        public class MarkRecordingsAsArchived : AssistRS
        { }

        public class TranscodeRecordings : AssistRS
        { }

        public class GetCompanies : AssistRS
        { }

        public class GetMachines : AssistRS
        { }

        public class GetScreenSharingSessionInfo : AssistRS
        { }

        public class GetSessions : AssistRS
        { }

        public class GetWebChatSessionInfo : AssistRS
        { }

        public class GetWebChatTranscriptInfo : AssistRS
        { }

        public class StartAttendedSessioninBrowser : AssistRS
        { }

        public class StartScreenSharingSession : AssistRS
        { }

        public class StartWebChatSession : AssistRS
        { }


    }

    public class AssistCorporate
    {
        public class CreateRepresentative : AssistCorporate
        { }

        public class CreateRepresentativesBulk : AssistCorporate
        { }

        public class DeleteRepresentative : AssistCorporate
        { }

        public class GetRepresentative : AssistCorporate
        { }

        public class GetRepresentatives : AssistCorporate
        { }

        public class UpdateRepresentative : AssistCorporate
        { }

        public class CreateTeam : AssistCorporate
        { }

        public class DeleteTeam : AssistCorporate
        { }

        public class GetTeam : AssistCorporate
        { }

        public class GetTeams : AssistCorporate
        { }

        public class GetPortal : AssistCorporate
        { }

        public class GetPortals : AssistCorporate
        { }





    }

    public class Auth
    {

        const string AuthUrl = "https://api.citrixonline.com/oauth/access_token";
        readonly string Grant_Type;
        readonly string User_ID;
        readonly string Password;
        readonly string Client_ID;

        public Auth(string User_ID, string Password, string ClientID)
        {
            Grant_Type = "password";
            this.User_ID = User_ID;
            this.Password = Password;
            this.Client_ID = ClientID;
        }

        protected T GetToken<T>(RestRequest request) where T : new()
        {
            var client = new RestClient();
            client.BaseUrl = AuthUrl;

            request.AddParameter("grant_type", Grant_Type, ParameterType.QueryString);
            request.AddParameter("user_id", User_ID, ParameterType.QueryString);
            request.AddParameter("password", Password, ParameterType.QueryString);
            request.AddParameter("client_id", Client_ID, ParameterType.QueryString);

            var response = client.Execute<T>(request);

            if (response.ErrorException != null || response.ErrorMessage != null)
            {
                var ConnectionException = new Exception(response.ErrorMessage);
                throw ConnectionException;
            }

            var RestException = new Exception(response.StatusCode.ToString());
            switch (response.StatusCode)
            {
                case System.Net.HttpStatusCode.OK:
                    break;
                case System.Net.HttpStatusCode.Created:
                    break;
                case System.Net.HttpStatusCode.BadGateway:
                    throw RestException;
                case System.Net.HttpStatusCode.BadRequest:
                    throw RestException;
                case System.Net.HttpStatusCode.Unauthorized:
                    throw RestException;
                case System.Net.HttpStatusCode.Forbidden:
                    throw RestException;
                case System.Net.HttpStatusCode.InternalServerError:
                    throw RestException;
                case System.Net.HttpStatusCode.NotFound:
                    throw RestException;
                case System.Net.HttpStatusCode.RequestTimeout:
                    throw RestException;
                default:
                    break;

            }
            return response.Data;
        }

        public class Response
        {
            public string Access_token { get; set; }
            public string Expires_in { get; set; }
            public string Refresh_token { get; set; }
            public string Organizer_key { get; set; }
            public string Account_key { get; set; }
            public string Account_type { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string Email { get; set; }

        }
        public Response GetToken()
        {
            var request = new RestRequest(Method.GET);
            return GetToken<Response>(request);
        }

    }

}


public static class StringExtension
{

    public static string ToISO8601UTC(this DateTime date)
    {

        return date.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ");
    }

    public static string RemoveDashes(this string String)
    {

        if (!String.IsNullOrEmpty(String))
        {
            String = String.Replace("-", "");
            return String;
        }

        else
        {
            return "";

        };
    }



}
